home *** CD-ROM | disk | FTP | other *** search
- {
- MD>What would anyone here recommend as being the best way for DOS
- >protected mode to get the current time of day *without* flipping
- >back to real mode to make a standard DOS call?
-
- If your code is allowed to talk to the real-time clock (RTC) chip,
- here's some example code to access the RTC directly. The functions
- work solely with 24-hr time format (if needed, internally by the RTC,
- they translate between 12/24-hr times and binary/BCD formats)...
- }
-
- (*******************************************************************)
- PROGRAM RClock; { Get/Set Time/Date directly from RTC chip }
- { June 9, 1994. Greg Vigneault }
- TYPE Treg = 0..$D; { range for time/date register addresses }
- To23 = 0..23; { range for hours }
- To59 = 0..59; { range for minutes and seconds }
- VAR Yr, Mth, Day, DoW, Hr, Min, Sec : BYTE;
-
- FUNCTION RTCbusy:BOOLEAN; BEGIN { RTC time/date being updated?... }
- Port[$70] := $A;; RTCbusy := (Port[$71] AND 128) = 128;
- END {RTCbusy};
-
- FUNCTION ReadReg (Reg:Treg):BYTE; BEGIN { read an RTC register... }
- IF Reg IN [0..9] THEN REPEAT {wait} UNTIL NOT RTCbusy;
- Port[$70] := Reg;; ReadReg := Port[$71];
- END {ReadReg};
-
- PROCEDURE WriteReg (Reg:Treg; Data:BYTE); { write RTC reg... }
- VAR temp:BYTE; BEGIN
- IF Reg IN [0..9] THEN BEGIN { time/date reg? }
- REPEAT {wait} UNTIL NOT RTCbusy;
- Port[$70] := $B;; temp := Port[$71];; Port[$71] := temp OR $80;
- END{IF};
- Port[$70] := Reg;; Port[$71] := Data;
- IF Reg IN [0..9] THEN BEGIN
- Port[$70] := $B;; Port[$71] := temp AND NOT $80;
- END{IF};
- END {WriteReg};
-
- FUNCTION BCD2Bin (BCD:BYTE):BYTE; BEGIN { xlate BCD to binary... }
- BCD2Bin := (BCD AND $0F) + ((BCD SHR 4) * 10);
- END {BCD2Bin};
- FUNCTION Bin2BCD (Bin:BYTE):BYTE; BEGIN { xlate binary to BCD... }
- Bin2BCD := (Bin MOD 10) OR BYTE((Bin DIV 10) SHL 4);
- END {Bin2BCD};
-
- PROCEDURE GetTime (VAR Hr,Min,Sec:BYTE);
- VAR temp:BYTE; BEGIN
- Sec := ReadReg(0);; Min := ReadReg(2);
- Hr := ReadReg(4);; temp := Hr;; Hr := Hr AND NOT $80;
- IF (ReadReg($B) AND 4) <> 4 THEN BEGIN { xlate BCD to bin... }
- Sec := BCD2Bin(Sec);; Min := BCD2Bin(Min);; Hr := BCD2Bin(Hr);
- END{IF};
- IF (ReadReg($B) AND 2) <> 2 THEN { RTC in 12-hr mode?... }
- IF (temp AND 128) = 128 { P.M.? }
- THEN BEGIN IF (Hr < 12) THEN INC(Hr,12); END
- ELSE IF Hr = 12 THEN Hr := 0;
- END {GetTime};
-
- PROCEDURE SetTime (Hr:To23; Min,Sec:To59);
- VAR temp:BYTE; BEGIN
- temp := BYTE(Hr);
- IF (ReadReg($B) AND 2) <> 2 THEN { RTC in 12-hr mode?... }
- IF (Hr > 12) THEN DEC(Hr,12) ELSE IF Hr = 0 THEN Hr := 12;
- IF (ReadReg($B) AND 4) <> 4 THEN BEGIN { RTC wants BCD format... }
- Hr := Bin2BCD(Hr);; Min := Bin2BCD(Min);; Sec := Bin2BCD(Sec);
- END{IF};
- IF ((ReadReg($B) AND 2)<>2) AND (temp > 11) THEN Hr := Hr OR $80;
- WriteReg(0,Sec);; WriteReg(2,Min);; WriteReg(4,Hr);
- END {SetTime};
-
- PROCEDURE GetDate (VAR Yr,Mth,Day:BYTE); BEGIN
- Day := ReadReg(7);; Mth := ReadReg(8);; Yr := ReadReg(9);
- IF (ReadReg($B) AND 4) <> 4 THEN BEGIN { xlate BCD to binay... }
- Day := BCD2Bin(Day);; Mth := BCD2Bin(Mth);; Yr := BCD2Bin(Yr);
- END; {IF}
- END {GetDate};
-
- PROCEDURE SetDate (Yr,Mth,Day:BYTE); BEGIN
- IF (ReadReg($B) AND 4) <> 4 THEN BEGIN { RTC wants BCD format... }
- Day := Bin2BCD(Day);; Mth := Bin2BCD(Mth);; Yr := Bin2BCD(Yr);
- END{IF};
- WriteReg(7,Day);; WriteReg(8,Mth);; WriteReg(9,Yr);
- END {SetDate};
-
- BEGIN {RClock}
- GetTime (Hr,Min,Sec);; GetDate (Yr,Mth,Day);; WriteLn;
- Write ('Date is ',Mth,'/',Day,'/',Yr,'. ');
- WriteLn ('Time is ',Hr,':',Min:2,':',Sec:2,'.');
- Write ('(BTW, your RTC is in ');
- IF (ReadReg($B) AND 2) <> 2 THEN Write ('12') ELSE Write ('24');
- Write ('-hour mode using ');
- IF (ReadReg($B) AND 4) <> 4 THEN Write('BCD') ELSE Write('binary');
- WriteLn (' format.)');
- END {RClock}.